import os
import re
import shutil

from pyx_package.script import BaseBehavior
from pyx_package.ps_paramete import PsParameter

PYX_MODULE_NAME = "file-copy"

class ScriptBehavior(BaseBehavior):

    def __init__(self) -> None:
        super().__init__()
        
        self.SetExeMode("function")
        self.InitParams()

    def InitParams(self):

        self.p_src_path = self.CreateParam("src path", "源文件路径", PsParameter.Input, str)
        self.p_dst_path = self.CreateParam("dst path", "目标文件路径", PsParameter.Input, str)
        self.p_cover = self.CreateParam("cover", "覆盖目标文件/文件夹", PsParameter.Input, bool)
        self.p_cover.value = False

        self.p_filter = self.CreateParam("filter", "过滤条件", PsParameter.Input, None)

        #需要忽略的文件
        self.p_ignore_file = self.CreateParam("ignore files", "忽略的文件", PsParameter.Input, list, [])
        self.p_ignore_file.value = []
        self.p_ignore_file.must = False
        self.p_filter.AddChild(self.p_ignore_file)

        #需要忽略的文件夹
        self.p_ignore_dirs = self.CreateParam("ignore dirs", "忽略的文件夹", PsParameter.Input, list, [])
        self.p_ignore_dirs.value = []
        self.p_ignore_dirs.must = False
        self.p_filter.AddChild(self.p_ignore_dirs)

        #符合的
        self.p_accord_file = self.CreateParam("accord files", "筛选符合条件的文件", PsParameter.Input, list, [])
        self.p_accord_file.value = []
        self.p_accord_file.must = False
        self.p_filter.AddChild(self.p_accord_file)

        #符合的
        self.p_accord_dir = self.CreateParam("accord dirs", "筛选符合条件的文件夹", PsParameter.Input, list, [])
        self.p_accord_dir.value = []
        self.p_accord_dir.must = False
        self.p_filter.AddChild(self.p_accord_dir)

    def DoStep(self):

        src_file = self.p_src_path.value
        dst_file = self.p_dst_path.value
    
        #判断路径是否存在
        if not os.path.exists(src_file):
            self.Debug("file is not exists: " + src_file, "error")
            return 

        #判断路径是否存在
        if os.path.exists(dst_file):

            #判断是否启用了覆盖
            if self.p_cover.value:

                #尝试删除已经存在的目标文件
                try:
                    if os.path.isdir(dst_file):
                        shutil.rmtree(dst_file)
                    elif os.path.isfile(dst_file):
                        os.remove(dst_file)
                except:
                    self.Debug("target file can't delete: " +  dst_file, "error")
                    return 

            else:
                self.Debug("target path is exists: " +  dst_file, "error")
                return 

        #判断原路径时文件还是文件夹
        if os.path.isfile(src_file):

            try:
                shutil.copyfile(src_file, dst_file)
            except:
                self.Debug("文件拷贝失败！", "error")


        else:
            try:
                shutil.copytree(src_file, dst_file,
                ignore = self.Ignore)
            except:
               self.Debug("文件夹拷贝失败！", "error")

    def Ignore(self, src, files):
        '''
            需要忽略的文件的回调函数
        '''
        src = src.replace("\\", "/")
        src = src.strip().rstrip("/")

        #忽略的列表
        ignore_list = []

        #符合条件的筛选器优先
        if len(self.p_accord_dir.value) > 0 or len(self.p_accord_file.value) > 0:

            for name in files:

                full_path = src + "/" + name

                #如果是文件夹，但是不符合添加，就忽略他
                if os.path.isdir(full_path) and not self.CheckFile(name, self.p_accord_dir.value):
                    ignore_list.append(name)

                if os.path.isfile(full_path) and not self.CheckFile(name, self.p_accord_file.value):
                    ignore_list.append(name)
        
        # 没有设置符合要求，就用忽略要求
        elif len(self.p_ignore_dirs.value) > 0 or len(self.p_ignore_file.value) > 0:

            for name in files:

                full_path = src + "/" + name

                #如果是文件夹，但是不符合添加，就忽略他
                if os.path.isdir(full_path) and self.CheckFile(name, self.p_ignore_dirs.value):
                    ignore_list.append(name)

                if os.path.isfile(full_path) and self.CheckFile(name, self.p_ignore_file.value):
                    ignore_list.append(name)

        return ignore_list

    def CheckFile(self, file_name, filter_list):
        '''
            判断一个文件/文件夹是否符合一个正则表达式列表
        '''

        #判断当前文件夹是否符合条件
        accord_flag = False

        for filter_str in filter_list:
            
            if re.search(filter_str, file_name) != None:
                accord_flag = True

        return accord_flag

        